﻿using System;

namespace DotNetStar.OpenSDK.WeChat.Pay
{
    using Payment;
    using System.ComponentModel.DataAnnotations;
    using System.Net.Http;

    /// <summary>
    /// 表示微信支付 api 请求的基类。
    /// </summary>
    /// <typeparam name="TResponse">The type of the response.</typeparam>
    /// <seealso cref="DotNetStar.OpenSDK.Payment.PaymentApiRequest{TResponse}" />
    [HttpPost]
    public abstract class WeChatPayApiRequest<TResponse> : PaymentApiRequest<TResponse>
        where TResponse : WeChatPayResponse
    {
        /// <summary>
        /// 初始化 <see cref="WeChatPayApiRequest{TResponse}"/> 类的新实例。
        /// </summary>
        /// <param name="requestUrl">请求的 api url 地址。</param>
        /// <param name="config">支付配置。</param>
        public WeChatPayApiRequest(string requestUrl, PaymentConfig config)
            : base(requestUrl, config, new WeChatPaySignatureHasher(config.SecurityKey))
        => this.Nonce_Str = Guid.NewGuid().ToString().Replace("-", string.Empty);
        /// <summary>
        /// 获取或设置订单号。
        /// </summary>
        /// <remarks>商户支付的订单号由商户自定义生成，微信支付要求商户订单号保持唯一性（建议根据当前系统时间加随机序列来生成订单号）。重新发起一笔支付要使用原订单号，避免重复支付；已支付过或已调用关单、撤销（请见后文的API列表）的订单号不能重新发起支付。</remarks>
        [StringLength(32)]
        public string Out_Trade_No { get; set; }

        /// <summary>
        /// 签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
        /// </summary>
        [Required]
        public string Sign_Type { get; set; } = "MD5";

        /// <summary>
        /// 获取应用的Id。
        /// </summary>
        [Required, StringLength(32)]
        public string AppId => base.Config.ClientId;

        /// <summary>
        /// 获取配置的商户号。
        /// </summary>
        [Required, StringLength(32)]
        public string Mch_Id => base.Config.MchId;

        /// <summary>
        /// 随机字符串。默认会自动生成一个。
        /// </summary>
        [Required, StringLength(32)]
        public string Nonce_Str { get; set; }

        /// <summary>
        /// 生成签名时不能带 sign 参数。
        /// 然后动态添加 sign 参数并转换为 xml。
        /// </summary>
        /// <param name="keyValue"><see cref="T:DotNetStar.OpenSDK.KeyValueCollection" /> 实例的动态对象，查看文档了解用法。</param>
        /// <returns>
        /// 微信 app 支付的 xml 格式字符串。
        /// </returns>
        public override dynamic OnArgumentsCreating(dynamic keyValue)
        {
            keyValue.sign = this.SignatureHasher.GenerateSignature(this);
            return keyValue.xml();
        }

        /// <summary>
        /// 处理自定义请求结果的回调。
        /// </summary>
        /// <param name="httpResponse">Http 请求响应的 <see cref="T:System.Net.Http.HttpResponseMessage" /> 实例。</param>
        /// <returns>
        /// 自定义的处理结果。
        /// </returns>
        public override TResponse ResponseHandler(HttpResponseMessage httpResponse)
        {
            var response = httpResponse.GetContentAsString();
            return new KeyValueCollection(response).ToObject<TResponse>();
        }
    }
}
